package reflect;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

/**
 * 类类型操作工具类
 * 
 * @author Administrator
 * @date 2018/03/02
 */
public class ClassUtils {

    /**
     * 得到类的成员方法信息
     * 
     * @param obj
     */
    public static void getClassMethodsMessage(Object obj) {
        Class<?> clzz = obj.getClass();
        // 类的名称
        System.out.println("类的名称是：" + clzz.getName());
        /**
         * Method类:方法对象 getMethods()方法获取的是所有public方法，包括父类继承而来的 getDeclaredMethods()方法是获取的所有该类的方法，不问访问权限
         */
        Method[] methods = clzz.getDeclaredMethods();
        for (Method method : methods) {
            // 得到返回值的类类型
            Class<?> returnType = method.getReturnType();
            System.out.print(returnType.getName() + " ");
            // 得到方法名称
            System.out.print(method.getName() + "(");
            // 得到方法参数
            Class<?>[] parameterTypes = method.getParameterTypes();
            int len = parameterTypes.length;
            if (len == 0) {
                System.out.println(")");
            }
            for (int i = 0; i < len; i++) {
                Class<?> c = parameterTypes[i];
                if (i == (len - 1)) {
                    System.out.println(c.getName() + ")");
                } else {
                    System.out.print(c.getName() + ",");
                }
            }
        }
    }

    /**
     * 得到类的成员变量信息
     * 
     * @param obj
     */
    public static void getClassFieldsMessage(Object obj) {
        Class<?> c = obj.getClass();
        Field[] declaredFields = c.getDeclaredFields();
        for (Field field : declaredFields) {
            Class<?> type = field.getType();
            // 成员变量类类型
            System.out.print(type.getName() + " ");
            System.out.print(field.getName());
            System.out.println();
        }
    }

    /**
     * 类的构造方法信息
     * 
     * @param obj
     */
    public static void getClassConstructorsMessage(Object obj) {
        Class<?> c = obj.getClass();
        Constructor<?>[] declaredConstructors = c.getDeclaredConstructors();
        for (Constructor<?> constructor : declaredConstructors) {
            // 成员变量的参数类型
            Class<?>[] parameterTypes = constructor.getParameterTypes();
            // 构造方法名
            String name = constructor.getName();
            int len = parameterTypes.length;
            if (len == 0) {
                System.out.println(")");
            }
            for (int i = 0; i < parameterTypes.length; i++) {
                Class<?> c2 = parameterTypes[i];
                // 构造方法修饰符
                String modifier = Modifier.toString(c2.getModifiers());
                System.out.print(modifier + " " + name + "(");
                if (i == (len - 1)) {
                    System.out.println(c2.getName() + ")");
                } else {
                    System.out.print(c2.getName() + ",");
                }
            }
        }
    }

    /**
     * 方法的反射
     * 
     * @param obj
     */
    public static void methodInvoke(Object obj) {
        Class<?> c = obj.getClass();
        try {
            // Method m = c.getMethod("print");
            Method m = c.getDeclaredMethod("print", new Class[] {});
            // 私有方法设置可调用
            m.setAccessible(true);
            // m.invoke(obj);
            m.invoke(obj, new Object[] {});

            // Method m2 = c.getDeclaredMethod("print", new Class[] {Integer.class, Integer.class});
            Method m2 = c.getDeclaredMethod("print", Integer.class, Integer.class);
            // 私有方法设置可调用
            m2.setAccessible(true);
            // m.invoke(obj);
            m2.invoke(obj, new Object[] {18, 32});

            Method m3 = c.getDeclaredMethod("print", String.class, String.class);
            // 私有方法设置可调用
            m3.setAccessible(true);
            m3.invoke(obj, "hello", " world");
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        // String a = "haha";
        getClassMethodsMessage(new Test());
        // getClassFieldsMessage(a);
        // getClassConstructorsMessage(a);
        // methodInvoke(new Test());
    }
}

class Test extends B {
    private void print() {
        System.out.println("nobody...");
    }

    private void print(String a, String b) {
        System.out.println(a + b);
    }

    private void print(Integer a, Integer b) {
        System.out.println(a + b);
    }
}

class B {
    public void hahaMethod() {

    }
}
